home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gekkan Dennou Club 147
/
Gekkan Dennou Club - 2000.8 Vol. 147 (Japan).7z
/
Gekkan Dennou Club - 2000.8 Vol. 147 (Japan) (Track 1).bin
/
docs
/
complex
/
mandel.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-06-05
|
4KB
|
196 lines
#include <stdio.h>
#include <setjmp.h>
#include <iocslib.h>
#include <math.h>
#include <time.h>
#include "complex.h"
#define USAGE "\
マンデルブロ集合を描く\n\
使用法: mandel [reMin imMax scLen [scSize [mxCnt]]]\n\
漸化式の初期値について reMin=実部最小, imMax=虚部最大, scLen=辺の長さ\n\
scSize=画面サイズ(0…256×256ドット, 1…512×512ドット)[0]\n\
mxCnt=回数制限(1~65535)[256]\n\
"
/* 画面サイズのデフォルト */
#define SC_SIZE 0
/* 計算範囲のデフォルト */
#define RE_MIN (-2.0)
#define IM_MAX (2.0)
#define SC_LEN (4.0)
/* 最大ループ回数のデフォルト */
#define MX_CNT 256
/* キーチェック */
#define keysns() \
({ \
int _k_ = 0; \
while (B_KEYSNS()) _k_ = B_KEYINP() & 0xff ? : _k_; \
_k_; \
})
double reMin = RE_MIN; /* 実部最小 */
double imMax= IM_MAX; /* 虚部最大 */
double scLen = SC_LEN; /* 辺の長さ */
int scSize = SC_SIZE; /* 画面サイズ(0…256×256ドット, 1…512×512ドット) */
int mxCnt = MX_CNT; /* 回数制限(1~65535) */
unsigned short *paTable; /* パレットテーブル */
void make_palet_table(void); /* パレットテーブルを作る */
void init_screen(void); /* 画面の初期化 */
void tini_screen(void); /* 画面の後始末 */
/* 初期値cでマンデルブロ集合の漸化式の反復回数を返す */
int iteration(complex c, int limit_cnt)
{
complex z;
int cnt;
if (setjmp(cjmpenv)) {
return limit_cnt; /* 計算できなかった */
}
cnt = limit_cnt;
z = c;
while (cnt > 0 && cabs2(z) <= 4.0) {
/* マンデルブロ集合の漸化式 z=z^2+c */
z = cadd(cpow2(z), c);
cnt--;
}
return limit_cnt - cnt;
}
/* 描画ルーチンの本体 */
void draw_body()
{
unsigned short *a;
complex c;
double step;
unsigned short scCnt;
unsigned short reCnt;
unsigned short imCnt;
complex c0;
scCnt = (scSize ? 512 : 256);
step = scLen / (double)scCnt;
/* VRAMの書き込みアドレス */
a = (unsigned short *)0xc00000;
c0 = tocomplex(reMin, imMax);
/* 虚軸方向のループ */
for (imCnt = 0; imCnt < scCnt; imCnt++) {
{
unsigned short *b;
b = a;
/* これから描画するラスタを示すための点線を描く */
for (reCnt = 0; reCnt < 512; reCnt += 8) {
*b = 0xffff;
b += 8;
}
}
c = c0;
/* 解像度に応じて実軸方向のループ全体を分ける */
if (scSize == 0) {
/* 256×256ドット */
/* 実軸方向のループ */
for (reCnt = 0; reCnt < scCnt; reCnt++) {
unsigned short col;
/* 漸化式の反復回数を数えてパレットテーブルを参照する */
col = paTable[iteration(c, mxCnt)];
/* 解像度に応じた大きさの点をVRAMに書き込む */
*a++ = col;
*a++ = col;
a[512-2] = col;
a[512-1] = col;
/* 実軸方向に進む */
Re(c) += step;
}
} else {
/* 512×512ドット */
/* 実軸方向のループ */
for (reCnt = 0; reCnt < scCnt; reCnt++) {
/* 漸化式の反復回数を数えてパレットテーブルを参照する */
/* 解像度に応じた大きさの点をVRAMに書き込む */
*a++ = paTable[iteration(c, mxCnt)];
/* 実軸方向に進む */
Re(c) += step;
}
}
/* 解像度に応じてVRAMの書き込みアドレスを補正する */
if (scSize == 0) {
a += 512;
}
/* 虚軸方向に進む */
Im(c0) -= step;
/* キーが押されたら中止 */
if (keysns()) {
break;
}
}
}
void main(int argc, char *argv[])
{
clock_t tm0, tm1;
/* 画面の初期化 */
init_screen();
/* コマンドラインのパラメータを取得 */
switch (argc) {
case 6:
sscanf(argv[5], "%d", &mxCnt);
case 5:
sscanf(argv[4], "%d", &scSize);
case 4:
sscanf(argv[3], "%lf", &scLen);
sscanf(argv[2], "%lf", &imMax);
sscanf(argv[1], "%lf", &reMin);
case 1:
break;
default:
printf(USAGE);
return;
}
/* パレットテーブルを作る */
make_palet_table();
/* スーパーバイザモードへ移行 */
B_SUPER(0);
/* 計測開始 */
{
clock_t t = clock();
while ((tm0 = clock()) == t);
}
/* 描画ルーチンの本体 */
draw_body();
/* 計測終了 */
tm1 = clock();
/* 画面の後始末 */
tini_screen();
/* 所要時間を表示 */
printf("所要時間は %.8g 秒です.\n", ((double)(tm1 - tm0)) / CLK_TCK);
}